package com.weishi.project.sport.movement.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.weishi.common.enums.RedisConstants;
import com.weishi.common.enums.TrainingProgramEnum;
import com.weishi.common.utils.DateUtils;
import com.weishi.common.utils.StringUtils;
import com.weishi.framework.config.ThreadPoolConfig;
import com.weishi.framework.redis.RedisCache;
import com.weishi.framework.web.domain.AjaxResult;
import com.weishi.project.mcs8.Mcs8Cilent;
import com.weishi.project.speedometer.domain.EmqMqttClient;
import com.weishi.project.speedometer.vo.DevInfo;
import com.weishi.project.sport.movement.selection.MovementSelection;
import com.weishi.project.sport.movement.service.MovementService;
import com.weishi.project.sport.movement.thread.MovementRunnable;
import com.weishi.project.sport.movement.vo.*;
import com.weishi.project.sport.trainingdata.vo.TypeValueVO;
import com.weishi.project.sport.trainingdata.vo.WaterRankingVO;
import com.weishi.project.system.service.ISysDictDataService;
import com.weishi.project.training.domain.*;
import com.weishi.project.training.service.*;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

/**
 * 运动员 运动模块 接口 实现类
 */
@Service
@Transactional
public class MovementServiceImpl implements MovementService {


    /**
     * 训练 周 计划接口
     */
    @Autowired
    private ITrainingWeekService trainingWeekService;

    /**
     * 训练 日 计划 接口
     */
    @Autowired
    private ITrainingDayService trainingDayService;

    /**
     * 请假表 接口
     */
    @Autowired
    private ILeaveFormService leaveFormService;

    /**
     * 分组表 接口
     */
    @Autowired
    private ITrainingGroupService trainingGroupService;

    @Autowired
    private ITrainingAchievementService trainingAchievementService;

    /**
     * 训练成绩 接口
     */
    @Autowired
    private ITrainingGroupChannelService trainingGroupChannelService;

    /**
     * redis 数据库
     */
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedisCache redisCache;

    /**
     * 注入线程池
     */
    @Resource
    private ThreadPoolConfig threadPoolConfig;

    /**
     * 运动模块增删改操作
     */
    @Autowired
    private MovementRunnable movementRunnable;

    /**
     * 心率表 接口
     */
    @Autowired
    private IHeartRateService heartRateService;

    /**
     * 字典子表 数据接口
     */
    @Autowired
    private ISysDictDataService dictDataService;

    /**
     * 测功仪数据接口
     */
    @Autowired
    private IDynamometerService dynamometerService;

    /**
     * 运动员接口
     */
    @Autowired
    private ISportsmanService sportsmanService;

    /**
     * 测功仪成绩排名 接口
     */
    @Autowired
    private IDynamometerRankingService dynamometerRankingService;

    @Autowired
    private IShipSpeedRecordService shipSpeedRecordService;

    /**
     * 心率计次数据
     */
    @Autowired
    private IHeartRateCountService heartRateCountService;

    /**
     * 测功仪分段数据 接口
     */
    @Autowired
    private IDynamometerSubsectionService dynamometerSubsectionService;

    /**
     * 赛后数据表Service接口
     */
    @Autowired
    private IRaceDataService raceDataService;

    @Autowired
    private IHeartRateRecordService heartRateRecordService;

    /**
     * 线程池设置为1，保持任务执行先后
     */
    private ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);


    private ScheduledExecutorService poollu = Executors.newScheduledThreadPool(6);


    /**
     * 运动员端--根据当前时间--查询我的运动计划列表--根据开始时间排序
     */
    @Override
    public AjaxResult getSportsPlan(String day, Integer userId) {

        // 1，首先查询这个运动员今天是否在请假中
        if (!sportsmanService.getById(userId).getStatus().equals("0")) {
            return AjaxResult.success("该运动员正在请假中！");
        } else {
            // 2，根据当前日期查询 训练计划 列表
            List<TrainingDay> trainingDayList = trainingDayService
                    .list(Wrappers.<TrainingDay>lambdaQuery()
                            .eq(TrainingDay::getDay, day)
                            .orderByAsc(TrainingDay::getStartTime));
            trainingDayList.forEach(p -> {
                // 判断天气 查询字典天气值
                List<TypeValueVO> sysDictDataList = dictDataService.getTypeValue("weather");
                sysDictDataList.forEach(pp -> {
                    if (StringUtils.isNotNull(p.getWeather()) && p.getWeather().equals(pp.getDictValue())) {
                        p.setWeather(pp.getDictLabel());
                    }
                });
                // 判断天气结束

                // 判断风速 查询字典风速值
                List<TypeValueVO> windSpeed = dictDataService.getTypeValue("wind_speed");
                windSpeed.forEach(pp -> {
                    if (StringUtils.isNotNull(p.getWindSpeed()) && p.getWindSpeed().equals(pp.getDictValue())) {
                        p.setWindSpeed(pp.getDictLabel());
                    }
                });
                // 判断风速结束

                // 判断场地因素 查询字典场地因素值
                List<TypeValueVO> siteFactors = dictDataService.getTypeValue("site_factors");
                siteFactors.forEach(pp -> {
                    if (StringUtils.isNotNull(p.getSiteFactors()) && p.getSiteFactors().equals(pp.getDictValue())) {
                        p.setSiteFactors(pp.getDictLabel());
                    }
                });
                // 判断场地因素 结束


            });
            return AjaxResult.success(trainingDayList);
        }
    }


    /**
     * 运动员端--查询运动计划详情
     */
    @Override
    public AjaxResult getSportsPlanDetails(Integer userId, String id) {
        TrainingDay trainingDay = trainingDayService.getById(id);
        Integer ids = Integer.parseInt(id);
        List<ReturnTrainingDayVO> trainingDayVOTwo = trainingDayService.getSportsPlanDetailsTwo(ids, userId);
        Map<Integer, ReturnTrainingDayVO> temp = new HashMap<>();
        if (trainingDayVOTwo != null) {
            // 直接根据 id 查询然后返回数据
            trainingDayVOTwo.forEach(p -> {
                temp.put(p.getGroupId(), p);
                // 判断场地因素结束

                // 查询分段成绩
                List<DynamometerSubsection> dynamometerSubsectionList = dynamometerSubsectionService
                        .list(Wrappers.<DynamometerSubsection>lambdaQuery()
                                .eq(DynamometerSubsection::getSportsmanId, p.getSportsmanId())
                                .eq(DynamometerSubsection::getTrainingDayId, p.getTrainingDayId())
                                .eq(DynamometerSubsection::getGroupId, p.getGroupId())
                                .orderByAsc(DynamometerSubsection::getSegmentNumber));

                // 平均心率
                Integer averageHeartRate = 0;
                //平均速度
                double averageSpeed = 0;
                // 平均浆频
                Integer propellerFrequency = 0;
                for (int i = 0; i < dynamometerSubsectionList.size(); i++) {
                    if (dynamometerSubsectionList.get(i).getHeartRate() > 0) {
                        averageHeartRate += dynamometerSubsectionList.get(i).getHeartRate();
                    }
                    if (StringUtils.isNotNull(dynamometerSubsectionList.get(i).getSpeed())) {
                        averageSpeed += dynamometerSubsectionList.get(i).getSpeed();
                    }
                    propellerFrequency += Integer.parseInt(dynamometerSubsectionList.get(i).getPropellerFrequency());
                }

                if (dynamometerSubsectionList.size() > 0) {
                    // 计算平均心率 并且存入字段值
                    if (averageHeartRate > 0) {
                        p.setAverageHeartRate(averageHeartRate / dynamometerSubsectionList.size());
                    }
                    // 计算平均速度 并且存入字段值
                    p.setAverageSpeed(averageSpeed / dynamometerSubsectionList.size());
                    // 计算平均浆频
                    Integer propellerFrequencys = propellerFrequency / dynamometerSubsectionList.size();
                    p.setPropellerFrequency(propellerFrequencys.toString());
                }


                /**
                 * 查询水上 平均心率，平均浆频
                 */
                if (trainingDay.getFirstLevel().equals(TrainingProgramEnum.WATERPROJECT.getKey())) {
                    // 查询航道 id
                    TrainingAchievement trainingAchievement = trainingAchievementService.getOne(Wrappers.<TrainingAchievement>lambdaQuery()
                            .eq(TrainingAchievement::getGroupId, p.getGroupId())
                            .eq(TrainingAchievement::getSportsmanId, userId));
                    if (StringUtils.isNotNull(trainingAchievement)) {
                        List<HeartRateCount> heartRateCountList = heartRateCountService
                                .listZHKID(trainingAchievement.getChannelId());
                        int countList = heartRateCountList.size();
                        List<Integer> heartRateCountListId = new ArrayList<>();
                        if (countList > 0) {
                            heartRateCountList.forEach(pp -> {
                                heartRateCountListId.add(pp.getId());
                            });
                            List<HeartRateRecord> heartRateRecordList = heartRateRecordService
                                    .list(Wrappers.<HeartRateRecord>lambdaQuery()
                                            .in(HeartRateRecord::getHeartRateCountId, heartRateCountListId)
                                            .eq(HeartRateRecord::getSportsmanId, userId)
                                            .orderByDesc(HeartRateRecord::getHeartRateAvg));
                            Integer averageHeartRates = 0;
                            for (int i = 0; i < heartRateRecordList.size(); i++) {
                                if (null != heartRateRecordList.get(i).getHeartRateAvg() && StringUtils.isNotNull(heartRateRecordList.get(i).getHeartRateAvg())) {
                                    averageHeartRates += heartRateRecordList.get(i).getHeartRateAvg();
                                }
                            }
                            if (averageHeartRates > 0) {
                                p.setAverageHeartRate(averageHeartRates / heartRateRecordList.size());
                            }

                            // 平均浆频
                            Integer propellerFrequencys = 0;
                            for (int k = 0; k < countList; k++) {
                                if(StringUtils.isNotNull(heartRateCountList.get(k).getPropellerFrequency()) && !"".equals(heartRateCountList.get(k).getPropellerFrequency())){
                                    propellerFrequencys += Integer.parseInt(heartRateCountList.get(k).getPropellerFrequency());
                                }
                            }
                            if (countList > 0 && propellerFrequencys > 0) {
                                Integer averagePropellerFrequency = propellerFrequencys / countList;
                                p.setPropellerFrequency(averagePropellerFrequency.toString());
                            }
                            // 水上结束
                        } else {
                            // 如果没查到值，全部赋值为 0
                            p.setHeartRate(0);
                        }
                    }
                }


                /**
                 * 根据课程 id 查询这个航道的所有人
                 * 重新赋值合作队员
                 */
                List<TrainingAchievement> trainingAchievementList = trainingAchievementService
                        .list(Wrappers.<TrainingAchievement>lambdaQuery()
                                .eq(TrainingAchievement::getChannelId, p.getChannelId()).notIn(TrainingAchievement::getSportsmanId, userId));
                String cooperationName = "";
                for (int i = 0; i < trainingAchievementList.size(); i++) {
                    cooperationName += trainingAchievementList.get(i).getSportsmanName() + " ";
                }
                p.setName(cooperationName);

            });
        }

        /**
         * 根据训练课 id 查询所有的组
         */
        List<TrainingGroup> trainingGroupList = trainingGroupService
                .list(Wrappers.<TrainingGroup>lambdaQuery()
                        .eq(TrainingGroup::getTrainingDayId, id));
        List<ReturnTrainingDayVO> ret = new ArrayList<>();
        for (TrainingGroup trainingGroup : trainingGroupList) {
            ReturnTrainingDayVO returnTrainingDayVO = new ReturnTrainingDayVO();
            StringUtils.copyProperties(trainingDay, returnTrainingDayVO);
            returnTrainingDayVO.setRealClassHour(trainingDay.getClassHour());
            if (temp.get(trainingGroup.getId()) != null) {
                StringUtils.copyProperties(temp.get(trainingGroup.getId()), returnTrainingDayVO);
            } else {
                returnTrainingDayVO.setSportsmanId(null);
                returnTrainingDayVO.setAchievement("");
                returnTrainingDayVO.setRowingKilometers(0.0);
                returnTrainingDayVO.setWatt("");
                returnTrainingDayVO.setName("");
                returnTrainingDayVO.setPower("");
                returnTrainingDayVO.setSr(null);
                returnTrainingDayVO.setPropellerFrequency("");
                returnTrainingDayVO.setGroupId(trainingGroup.getId());
            }
            // 判断浆位
            if (returnTrainingDayVO.getOarType() == null) {
                returnTrainingDayVO.setOarTypeName("");
            } else if (returnTrainingDayVO.getOarType() == 0) {
                returnTrainingDayVO.setOarTypeName("双桨");
            } else if (returnTrainingDayVO.getOarType() == 1) {
                returnTrainingDayVO.setOarTypeName("左桨");
            } else if (returnTrainingDayVO.getOarType() == 2) {
                returnTrainingDayVO.setOarTypeName("右桨");
            }

            // 判断号位
            if (returnTrainingDayVO.getPosition() == null) {
                returnTrainingDayVO.setPositionName("");
            } else if (returnTrainingDayVO.getPosition() == -1) {
                returnTrainingDayVO.setPositionName("舵手");
            } else {
                returnTrainingDayVO.setPositionName(returnTrainingDayVO.getPosition().toString());
            }

            if (returnTrainingDayVO.getTrainingMode() == 0) {
                returnTrainingDayVO.setTrainingModeName("公里数");
            } else {
                returnTrainingDayVO.setTrainingModeName("时间");
            }

            // 判断时间或者公里数手段
            if (trainingDay.getTrainingMode() == 1) {
                returnTrainingDayVO.setRealClassHour(trainingDay.getRealClassHour());
            }

            returnTrainingDayVO.setGroupName(trainingGroup.getGroupName());
            returnTrainingDayVO.setRealClassHour(trainingDay.getClassHour());
            ret.add(returnTrainingDayVO);
        }

        return AjaxResult.success(ret);
    }


    /**
     * 运动员端--查询运动--乳酸
     */
    @Override
    public AjaxResult getLacticAcid(Integer userId, String firstLevel, Integer trainingMode, Integer groupId, Integer trainingDayId) {
        List<RaceData> raceDataList = raceDataService.list(Wrappers.<RaceData>lambdaQuery()
                .eq(RaceData::getSportsmanId, userId)
                .eq(RaceData::getTrainingDayId, trainingDayId)
                .eq(RaceData::getGroupId , groupId)
                .orderByDesc(RaceData::getCtime));
        if(raceDataList.size() > 0)raceDataList.forEach( p-> {
                if(StringUtils.isNull(p.getHeartRate())){
                    p.setHeartRate("0");
                }
                if(StringUtils.isNull(p.getHeartRateTitle())){
                    p.setHeartRateTitle("无");
                }
                if(StringUtils.isNull(p.getLacticAcidTitle())){
                    p.setLacticAcidTitle("无");
                }
                if(StringUtils.isNull(p.getLacticAcid())){
                    p.setLacticAcid("0");
                }
                if(StringUtils.isNull(p.getMaxHeartRate())){
                    p.setMaxHeartRate(0);
                }
        });
        return AjaxResult.success(raceDataList);
    }


    /**
     * 运动员端--查询运动--专项成绩信息
     */
    @Override
    public AjaxResult getWaterInformation(Integer userId, Integer id, Integer trainingMode, String firstLevel, Integer groupId) {
        /**
         * 判断水上陆上
         */
        if (firstLevel.equals("special_training_water")) {
            // 查询记次表
            List<Map<String, Object>> ret = new ArrayList<>();
            List<HeartRateCount> heartRateCountList = heartRateCountService.selectHeartRateCountList(groupId, userId);
            for (HeartRateCount heartRateCount : heartRateCountList) {
                try {
                    Map<String, Object> tempMap = HeartRateCount.toMap(heartRateCount);
                    HeartRateRecord params = new HeartRateRecord();
                    params.setHeartRateCountId(heartRateCount.getId());
                    params.setSportsmanId(userId);
                    List<HeartRateRecord> heartRateRecords = heartRateRecordService.selectHeartRateRecordList(params);
                    if (!heartRateRecords.isEmpty()) {
                        tempMap.put("hr", heartRateRecords.get(0).getHeartRateAvg());
                    }
                    ret.add(tempMap);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            return AjaxResult.success(ret);
        } else {
            // 陆上查询
            // 查询这个人的所有分段
            List<DynamometerSubsection> dynamometerSubsectionList = dynamometerSubsectionService
                    .list(Wrappers.<DynamometerSubsection>lambdaQuery()
                            .eq(DynamometerSubsection::getSportsmanId, userId)
                            .eq(DynamometerSubsection::getTrainingDayId, id)
                            .eq(DynamometerSubsection::getTrainingMode, trainingMode)
                            .eq(DynamometerSubsection::getGroupId, groupId)
                            .orderByAsc(DynamometerSubsection::getSegmentNumber));

            List<DynamometerSubsection> dynamometerSubsectionList2 = new ArrayList<>();
            if (dynamometerSubsectionList.size() > 0) {
                if (dynamometerSubsectionList.size() == 1) {
                    dynamometerSubsectionList2.add(dynamometerSubsectionList.get(0));
                    return AjaxResult.success(dynamometerSubsectionList2);
                } else {

                    // 总数据
                    int size = dynamometerSubsectionList.size();
                    // 起始数
                    int index = 0;
                    for (int i = 0; i < dynamometerSubsectionList.size(); i++) {
                        //  trainingMode =  0 减时间  1 减距离
                        if (dynamometerSubsectionList.get(i).getTrainingMode() == 0) {
                            if (index < size) {
                                DynamometerSubsection dynamometerSubsection = new DynamometerSubsection();
                                StringUtils.copyProperties(dynamometerSubsectionList.get(i), dynamometerSubsection);
                                if (index == 0) {
                                    dynamometerSubsectionList2.add(dynamometerSubsection);
                                } else {
                                    System.out.println();
                                    Long lengthTime = StringUtils.turnSecond(dynamometerSubsectionList.get(i).getLengthTime());
                                    Long lengthTime2 = StringUtils.turnSecond(dynamometerSubsectionList.get(index - 1).getLengthTime());
                                    Long lengthTime3 = lengthTime - lengthTime2;
                                    dynamometerSubsection.setLengthTime(StringUtils.millisecondRotationTime(lengthTime3));
                                    dynamometerSubsectionList2.add(dynamometerSubsection);
                                }
                                index++;
                            }

                        } else {

                            if (index < size) {
                                DynamometerSubsection dynamometerSubsection = new DynamometerSubsection();
                                StringUtils.copyProperties(dynamometerSubsectionList.get(i), dynamometerSubsection);
                                if (index == 0) {
                                    dynamometerSubsectionList2.add(dynamometerSubsection);
                                } else {
                                    double mileage = dynamometerSubsectionList.get(i).getMileage();
                                    double mileage2 = dynamometerSubsectionList.get(index - 1).getMileage();
                                    double mileage3 = mileage - mileage2;
                                    dynamometerSubsection.setMileage(mileage3);
                                    dynamometerSubsectionList2.add(dynamometerSubsection);
                                }
                                index++;
                            }

                        }


                    }
                    return AjaxResult.success(dynamometerSubsectionList2);
                }

            }
            return AjaxResult.success();
        }
    }


    /**
     * 运动员端--查询运动--专项成绩信息--成绩对标
     */
    @Override
    public AjaxResult getWaterAlignment(Integer userId, Integer id, Integer trainingMode, String firstLevel, Integer groupId) {
        AlignmentVO alignmentVO = new AlignmentVO();

        // 根据课 id 组 id 运动员 id 查询航道 id
        List<TrainingAchievement> trainingAchievementList = trainingAchievementService
                .list(Wrappers.<TrainingAchievement>lambdaQuery()
                        .eq(TrainingAchievement::getGroupId , groupId)
                        .eq(TrainingAchievement::getSportsmanId , userId));
        TrainingGroupChannel trainingGroupChannel = trainingGroupChannelService.getById(trainingAchievementList.get(0).getChannelId());

        String boatType = "";
        String achievement = "";

        // 查询本次成绩
        List<ReturnTrainingDayVO> returnTrainingDayVO = trainingDayService.getWaterInformation(userId, id, trainingMode, firstLevel, groupId);
        if (returnTrainingDayVO.size() > 0) {
            // 查询运动员专项最好成绩
            if(trainingAchievementList.size() > 0){
                boatType = trainingGroupChannel.getBoatType();
                achievement = trainingGroupChannel.getAchievement();
                alignmentVO.setThisResult(achievement);
                alignmentVO.setPersonalBest(trainingDayService.getPersonalBest(boatType , trainingGroupChannel.getRowingKilometers() , userId, trainingMode, firstLevel));
            }
        }

        // 与冠军的差值
        // 判断 trainingMode  0 或者是 1
        if (trainingMode == 0) {
            if (StringUtils.isNotNull(trainingDayService.getPersonalBest(boatType , trainingGroupChannel.getRowingKilometers() , userId, trainingMode, firstLevel))
                    && !"".equals(trainingDayService.getPersonalBest(boatType , trainingGroupChannel.getRowingKilometers() , userId, trainingMode, firstLevel))) {
                //个人最好成绩
                Long individual = StringUtils.turnSecond(trainingDayService.getPersonalBest(boatType , trainingGroupChannel.getRowingKilometers() , userId, trainingMode, firstLevel));
                //本次成绩
                Long champion = 0L;
                if (returnTrainingDayVO.size() > 0) {
                    alignmentVO.setThisResult(achievement);
                    champion = StringUtils.turnSecond(achievement);
                }
                if (champion <= individual) {
                    Long value = individual - champion;
                    if (value > 0L) {
                        alignmentVO.setChampionship(StringUtils.millisecondRotationTime(value));
                    } else {
                        alignmentVO.setChampionship("00:00:00.000");
                    }
                } else {
                    Long value = champion - individual;
                    if (value > 0L) {
                        alignmentVO.setChampionship(StringUtils.millisecondRotationTime(value));
                    } else {
                        alignmentVO.setChampionship("00:00:00.000");
                    }
                }
            }

            // trainingMode == 1
        } else {

            if (StringUtils.isNotNull(trainingDayService.getPersonalBest(boatType , trainingGroupChannel.getRowingKilometers() , userId, trainingMode, firstLevel))
                    && !"".equals(trainingDayService.getPersonalBest(boatType , trainingGroupChannel.getRowingKilometers() , userId, trainingMode, firstLevel))) {
                //个人最好成绩
                Double individual = Double.parseDouble(trainingDayService.getPersonalBest(boatType , trainingGroupChannel.getRowingKilometers() , userId, trainingMode, firstLevel));
                //本次成绩
                Double champion = 0.0;
                if (returnTrainingDayVO.size() > 0) {
                    alignmentVO.setThisResult(achievement);
                    champion = Double.parseDouble(achievement);
                }
                if (champion <= individual) {
                    Double value = individual - champion;
                    if (value > 0L) {
                        alignmentVO.setChampionship(value.toString());
                    } else {
                        alignmentVO.setChampionship("0.0");
                    }
                } else {
                    Double value = champion - individual;
                    if (value > 0L) {
                        alignmentVO.setChampionship(value.toString());
                    } else {
                        alignmentVO.setChampionship("0.0");
                    }
                }
            }

        }

        return AjaxResult.success(alignmentVO);
    }


    /**
     * 运动员端--查询运动--专项成绩信息--船速及浆频
     */
    @Override
    public AjaxResult getWaterShipPulp(Integer userId, Integer id, Integer trainingMode, String firstLevel, Integer groupId) {
        return AjaxResult.success(trainingDayService.getWaterInformation(userId, id, trainingMode, firstLevel, groupId));
    }


    Logger logger = Logger.getLogger("HeartRate");

    /**
     * 运动员端--运动模块--新增心率
     */
    @Override
    public AjaxResult addHeartRate(Integer userId, HeartRate heartRate) {
        logger.info("heartRate:" + userId + " msg:" + heartRate.toString());
        try {
            Integer channelId = redisCache.getCacheObject(RedisConstants.Heart_Rate_Meter_Prefix + userId);
            if (channelId != null) {
                heartRate.setSportsmanId(userId);
                heartRate.setChannelId(channelId);
                heartRate.setCtime(new Date());
                Integer countId = redisCache.getCacheObject(RedisConstants.Channel_count_Prefix + channelId);
                if (countId == null) {
                    countId = 1;
                }
                heartRate.setHeartRateCountId(countId);
                heartRateService.save(heartRate);
            }
            return AjaxResult.success();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.error("系统异常！");
    }


    /**
     * 运动员端--运动模块--查询测功仪数据
     */
    @Override
    public AjaxResult getDynamometerList(Integer userId, Integer groupId, Integer trainingDayId) {
        List<Dynamometer> dynamometerList = dynamometerService.list(Wrappers.<Dynamometer>lambdaQuery().eq(Dynamometer::getSportsmanId, userId).eq(Dynamometer::getGroupId, groupId).eq(Dynamometer::getTrainingDayId, trainingDayId).orderByDesc(Dynamometer::getCtime));
        if (dynamometerList.size() > 0) {
            return AjaxResult.success(dynamometerList.get(0));
        } else {
            return AjaxResult.success();
        }
    }


    /**
     * 运动员端--教练点击开始按钮
     */
    @Override
    public AjaxResult start(JSONObject jsonObject) {
        Date date = new Date();
        pool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    // 更新航道的开始时间
                    TrainingGroupChannel channel = new TrainingGroupChannel();
                    channel.setStime(date);
                    channel.setId(Integer.parseInt(jsonObject.get("channelId").toString()));
                    trainingGroupChannelService.updateById(channel);

                    //启动船速仪设备计时
                    TrainingGroupChannel trainingGroupChannel = trainingGroupChannelService.getById(Integer.parseInt(jsonObject.get("channelId").toString()));
                    if (trainingGroupChannel.getShipSpeedId() != null) {
                        //船速仪开始计时,有效期3个小时
                        redisCache.setCacheObject(RedisConstants.Channel_ShipSpeed_Status_Prefix + trainingGroupChannel.getShipSpeedId(), trainingGroupChannel.getId(), 3, TimeUnit.HOURS);

                        //开启消息队列向设置通信
                        EmqMqttClient.getInstance().setNoticeQueue(trainingGroupChannel.getShipSpeedId(),trainingGroupChannel.getId());

                        DevInfo devInfo = redisCache.getCacheObject(RedisConstants.Dev_Info_Prefix + trainingGroupChannel.getShipSpeedId());
                        if (devInfo == null) {
                            devInfo = new DevInfo();
                        }

                        devInfo.setDevId(trainingGroupChannel.getShipSpeedId());
                        devInfo.setChannelId(channel.getId());
                        devInfo.setEndTime("");
                        devInfo.setSpeed(0);
                        devInfo.setDistance(0);
                        devInfo.setPropellerFrequency(0);
                        devInfo.setRealTime();
                        devInfo.setStartTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, new Date()));
                        redisCache.setCacheObject(RedisConstants.Dev_Info_Prefix + trainingGroupChannel.getShipSpeedId(), devInfo);
                    }

                    //启动心率表的数据（水上）
                    TrainingAchievement params = new TrainingAchievement();
                    params.setChannelId(trainingGroupChannel.getId());
                    List<TrainingAchievement> list = trainingAchievementService.selectTrainingAchievementList(params);
                    if (StringUtils.isNotEmpty(trainingGroupChannel.getBoatType()) && list != null && list.size() > 0) {
                        for (TrainingAchievement trainingAchievement : list) {
                            //心率表开始计数,有效期3个小时
                            redisCache.setCacheObject(RedisConstants.Heart_Rate_Meter_Prefix + trainingAchievement.getSportsmanId(), trainingGroupChannel.getId(), 3, TimeUnit.HOURS);
                        }
                    }

                    //开启视频录制
                    Mcs8Cilent mcs8Cilent = Mcs8Cilent.getInstant();
                    if (StringUtils.isNotEmpty(trainingGroupChannel.getSeat2()))
                        mcs8Cilent.startRecording(trainingGroupChannel.getSeat2(), 1);
                    if (StringUtils.isNotEmpty(trainingGroupChannel.getSeat1()))
                        mcs8Cilent.startRecording(trainingGroupChannel.getSeat1(), 1);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        return AjaxResult.success();
    }


    /**
     * 运动员端--教练点击结束按钮
     */
    @Override
    public AjaxResult end(JSONObject jsonObject) {
        // 更新航道的结束时间
        TrainingGroupChannel channel = new TrainingGroupChannel();
        channel.setEtime(new Date());
        channel.setId(Integer.parseInt(jsonObject.get("channelId").toString()));
        trainingGroupChannelService.updateById(channel);

        //关闭船速仪设备计时
        TrainingGroupChannel trainingGroupChannel = trainingGroupChannelService.getById(Integer.parseInt(jsonObject.get("channelId").toString()));
        if (trainingGroupChannel.getShipSpeedId() != null) {
            DevInfo devInfo = redisCache.getCacheObject(RedisConstants.Dev_Info_Prefix + trainingGroupChannel.getShipSpeedId());
            if (devInfo != null) {
                devInfo.setChannelId(0);
                devInfo.setEndTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, new Date()));
            }
            redisCache.setCacheObject(RedisConstants.Dev_Info_Prefix + trainingGroupChannel.getShipSpeedId(), devInfo);
            //船速仪结束计时
            redisCache.deleteObject(RedisConstants.Channel_ShipSpeed_Status_Prefix + trainingGroupChannel.getShipSpeedId());
            //关闭消息队列向设置通信
            EmqMqttClient.getInstance().setNoticeQueue(trainingGroupChannel.getShipSpeedId(),0);
            //核算成绩
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    //防止最后一计次未入库
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    shipSpeedRecordService.addShipSpeedRecord(trainingGroupChannel.getShipSpeedId(), trainingGroupChannel.getId());
                }
            });
        }

        //关闭心率表设备计数
        TrainingAchievement params = new TrainingAchievement();
        params.setChannelId(trainingGroupChannel.getId());
        List<TrainingAchievement> list = trainingAchievementService.selectTrainingAchievementList(params);
        if (StringUtils.isNotEmpty(trainingGroupChannel.getBoatType()) && list != null && list.size() > 0) {
            redisCache.deleteObject(RedisConstants.Channel_count_Prefix + trainingGroupChannel.getId());
            for (TrainingAchievement trainingAchievement : list) {
                //心率表开始计数,有效期3个小时
                redisCache.deleteObject(RedisConstants.Heart_Rate_Meter_Prefix + trainingAchievement.getSportsmanId());
            }

            //核算成绩
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    //防止最后一计次未入库
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    heartRateRecordService.addRecord(trainingGroupChannel.getId());
                }
            });
        }

        //关闭视频录制
        pool.execute(new Runnable() {
            @Override
            public void run() {
                Mcs8Cilent mcs8Cilent = Mcs8Cilent.getInstant();
                if (StringUtils.isNotEmpty(trainingGroupChannel.getSeat2()))
                    mcs8Cilent.stopRecording(trainingGroupChannel.getSeat2(), 1);
                if (StringUtils.isNotEmpty(trainingGroupChannel.getSeat1()))
                    mcs8Cilent.stopRecording(trainingGroupChannel.getSeat1(), 1);
            }
        });

        return AjaxResult.success();
    }



    /**
     * 运动员端--新增测功仪数据
     */
    @Override
    public AjaxResult addDynamometer(JSONObject trainingReportBean, Integer userId) {
        try {
            TrainingReportBean trainingDetails = JSONObject.toJavaObject(trainingReportBean, TrainingReportBean.class);//将建json对象转换为Person对象
            if (StringUtils.isNull(trainingDetails)) {
                return AjaxResult.error("数据不能为空！");
            }
            trainingDetails.setUserId(userId);
            redisTemplate.boundListOps("MovementServiceImpl_addDynamometer_trainingReportBean").leftPush(trainingDetails);
            MovementSelection.setValue("MovementServiceImpl_addDynamometer");
            threadPoolConfig.threadPoolTaskExecutor().execute(movementRunnable);

        }catch (Exception e){
            logger.info(e.getMessage());
        }
        return AjaxResult.success();
    }


    /**
     * 运动员端--根据训练日 id  用户 userId 查询数据
     */
    @Override
    public AjaxResult getTrainingDayById(Integer id, Integer userId) {
        return AjaxResult.success(dynamometerService.list(Wrappers.<Dynamometer>lambdaQuery().eq(Dynamometer::getTrainingDayId, id).eq(Dynamometer::getSportsmanId, userId).orderByDesc(Dynamometer::getCtime)));
    }


    /**
     * 运动员端--根据主键删除测功仪数据
     */
    @Override
    public AjaxResult deleteDynamometerById(Integer id) {
        dynamometerService.removeById(id);
        return AjaxResult.success();
    }


    /**
     * 运动员端--根据主键 修改 测功仪数据
     */
    @Override
    public AjaxResult updateDynamometerById(Dynamometer dynamometer) {
        dynamometerService.updateById(dynamometer);
        return AjaxResult.success();
    }


    /**
     * 运动员端--测功仪--查询心率
     */
    @Override
    public AjaxResult getDynamometerHeartRate(Integer userId, Integer trainingDayId, Integer trainingMode, Integer groupId) {
        return AjaxResult.success(dynamometerSubsectionService
                .list(Wrappers.<DynamometerSubsection>lambdaQuery()
                        .eq(DynamometerSubsection::getSportsmanId, userId)
                        .eq(DynamometerSubsection::getTrainingDayId, trainingDayId)
                        .eq(DynamometerSubsection::getTrainingMode, trainingMode)
                        .eq(DynamometerSubsection::getGroupId, groupId)
                        .orderByAsc(DynamometerSubsection::getCtime)));
    }


    /**
     * 运动员端--心率表--查询心率
     */
    @Override
    public AjaxResult getHeartRateList(Integer userId, Integer trainingDayId, Integer groupId) {
        List<Integer> heartRateCountListId = new ArrayList<>();
        TrainingAchievement trainingAchievement = trainingAchievementService.getOne(Wrappers.<TrainingAchievement>lambdaQuery()
                .eq(TrainingAchievement::getGroupId, groupId)
                .eq(TrainingAchievement::getSportsmanId, userId));
        if (StringUtils.isNotNull(trainingAchievement)) {
            List<HeartRateCount> heartRateCountList = heartRateCountService
                    .listZHKID(trainingAchievement.getChannelId());
            if (heartRateCountList.size() > 0) {
                heartRateCountList.forEach(p -> {
                    heartRateCountListId.add(p.getId());
                });
                List<HeartRateRecord> heartRateRecordList = heartRateRecordService
                        .list(Wrappers.<HeartRateRecord>lambdaQuery()
                                .in(HeartRateRecord::getHeartRateCountId, heartRateCountListId)
                                .eq(HeartRateRecord::getSportsmanId, userId)
                                .orderByDesc(HeartRateRecord::getHeartRateAvg));
                return AjaxResult.success(heartRateRecordList);
            } else {
                return AjaxResult.success(heartRateCountListId);
            }
        } else {
            return AjaxResult.success(heartRateCountListId);
        }
    }


    /**
     * 运动员端--计算平均心率，最大心率
     */
    @Override
    public AjaxResult getAverageAndMax(Integer userId, Integer trainingDayId, Integer trainingMode, Integer groupId, String firstLevel) {
        AverageAndMaxVO averageAndMaxVO = new AverageAndMaxVO();

        /**
         * 判断水上，还是陆上
         * 陆上 land_specific_training_dynamometer
         * 水上 special_training_water
         */
        if (firstLevel.equals("land_specific_training_dynamometer")) {
            // 陆上
            List<DynamometerSubsection> dynamometerSubsectionList = dynamometerSubsectionService
                    .list(Wrappers.<DynamometerSubsection>lambdaQuery()
                            .eq(DynamometerSubsection::getSportsmanId, userId)
                            .eq(DynamometerSubsection::getTrainingDayId, trainingDayId)
                            .eq(DynamometerSubsection::getTrainingMode, trainingMode)
                            .eq(DynamometerSubsection::getGroupId, groupId)
                            .orderByDesc(DynamometerSubsection::getHeartRate));
            if (dynamometerSubsectionList.size() > 0) {
                // 测功仪最大心率
                averageAndMaxVO.setMaxHeartRate(dynamometerSubsectionList.get(0).getHeartRate());
            }
            // 计算测功仪平均心率
            Integer averageHeartRate = 0;
            for (int i = 0; i < dynamometerSubsectionList.size(); i++) {
                averageHeartRate += dynamometerSubsectionList.get(i).getHeartRate();
            }
            if (averageHeartRate > 0) {
                averageAndMaxVO.setAverageHeartRate(averageHeartRate / dynamometerSubsectionList.size());
            }
            // 陆上结束

        } else {
            // 水上
            // 查询航道 id
            TrainingAchievement trainingAchievement = trainingAchievementService.getOne(Wrappers.<TrainingAchievement>lambdaQuery()
                    .eq(TrainingAchievement::getGroupId, groupId)
                    .eq(TrainingAchievement::getSportsmanId, userId));
            if (StringUtils.isNotNull(trainingAchievement)) {
                List<HeartRateCount> heartRateCountList = heartRateCountService
                        .listZHKID(trainingAchievement.getChannelId());
                List<Integer> heartRateCountListId = new ArrayList<>();
                if (heartRateCountList.size() > 0) {
                    heartRateCountList.forEach(p -> {
                        heartRateCountListId.add(p.getId());
                    });
                    List<HeartRateRecord> heartRateRecordList = heartRateRecordService
                            .list(Wrappers.<HeartRateRecord>lambdaQuery()
                                    .in(HeartRateRecord::getHeartRateCountId, heartRateCountListId)
                                    .eq(HeartRateRecord::getSportsmanId, userId)
                                    .orderByDesc(HeartRateRecord::getHeartRateAvg));
                    // 最大心率
                    if (heartRateRecordList.size() > 0) {
                        if (null != heartRateRecordList.get(0).getHeartRateAvg() && StringUtils.isNotNull(heartRateRecordList.get(0).getHeartRateAvg())) {
                            averageAndMaxVO.setMaxHeartRate(heartRateRecordList.get(0).getHeartRateAvg());
                        }
                    }

                    Integer averageHeartRate = 0;
                    for (int i = 0; i < heartRateRecordList.size(); i++) {
                        if (null != heartRateRecordList.get(i).getHeartRateAvg() && StringUtils.isNotNull(heartRateRecordList.get(i).getHeartRateAvg())) {
                            averageHeartRate += heartRateRecordList.get(i).getHeartRateAvg();
                        }
                    }
                    if (averageHeartRate > 0) {
                        averageAndMaxVO.setAverageHeartRate(averageHeartRate / heartRateRecordList.size());
                    }else{
                        averageAndMaxVO.setAverageHeartRate(0);
                    }
                    // 水上结束
                } else {
                    // 如果没查到值，全部赋值为 0
                    averageAndMaxVO.setMaxHeartRate(0);
                    averageAndMaxVO.setAverageHeartRate(0);
                }
            }
        }
        return AjaxResult.success(averageAndMaxVO);
    }


    /**
     * 运动员 -- 今日专项成绩排名
     */
    @Override
    public AjaxResult getThisDayRanking(Integer groupId, String boatType, Integer trainingDayId, Integer sex, Integer trainingMode, Integer kilometers, Double realClassHour, String firstLevel) {
        Integer ranking = 0;
        List<WaterRankingVO> waterRankingVOList = new ArrayList<>();
        List<WaterRankingVO> waterRankingVOListTwo = trainingAchievementService.getThisDayRankingVO(groupId, boatType, trainingDayId, sex, trainingMode, kilometers, realClassHour, firstLevel);
        // 获取所有人的名称
        List<String> nameList = new ArrayList<>();
        for (int i = 0; i < waterRankingVOListTwo.size(); i++) {
            WaterRankingVO waterRankingVO = new WaterRankingVO();
            StringUtils.copyProperties(waterRankingVOListTwo.get(i), waterRankingVO);
            waterRankingVO.setRanking(ranking += 1);
            waterRankingVOList.add(waterRankingVO);
            nameList.add(waterRankingVOListTwo.get(i).getName());
        }

        // 删除重复的 list
        List<String> newList = new ArrayList<>();
        for (String cd : nameList) {
            if (!newList.contains(cd)) {
                newList.add(cd);
            }
        }

        List<WaterRankingVO> waterRankingVOListTwo2 = new ArrayList<>();
        for (int i = 0; i < newList.size(); i++) {
            // 根据 运动员名称查询排名
            WaterRankingVO waterRankingVO = new WaterRankingVO();
            StringUtils.copyProperties(trainingAchievementService.getThisDayRankingVOSS(groupId , firstLevel, newList.get(i), trainingMode, kilometers, sex).get(0), waterRankingVO);
            waterRankingVO.setRanking(i + 1);
            for (int j = 0; j<waterRankingVOListTwo2.size(); j++ ){
                if(waterRankingVOListTwo2.get(j).getAchievement().equals(trainingAchievementService.getThisDayRankingVOSS(groupId , firstLevel, newList.get(i), trainingMode, kilometers, sex).get(0).getAchievement())){
                    waterRankingVO.setName(waterRankingVOListTwo2.get(j).getName()+"/"+trainingAchievementService.getThisDayRankingVOSS(groupId , firstLevel, newList.get(i), trainingMode, kilometers, sex).get(0).getName());
                    waterRankingVOListTwo2.remove(j);
                }
            }
            waterRankingVOListTwo2.add(waterRankingVO);
        }
        return AjaxResult.success(waterRankingVOListTwo2);
    }


    /**
     * 运动员 -- 测功仪存储分段成绩
     */
    @Override
    public AjaxResult addDynamometerSubsection(Integer userId, DynamometerSubsection dynamometerSubsection) {
        dynamometerSubsection.setSportsmanId(userId);
        dynamometerSubsection.setCtime(new Date());

        if (dynamometerSubsection.getSpeed() > 0.0) {
            // 计算四舍五入
            double d = dynamometerSubsection.getSpeed();
            d = Math.round(d * 100) / 100.0;
            dynamometerSubsection.setSpeed(d);
        }
        // 成绩转换 格式为 00:00:00.000
        Long achievement = StringUtils.turnSecond(dynamometerSubsection.getLengthTime());
        dynamometerSubsection.setLengthTime(StringUtils.millisecondRotationTime(achievement));
        // 功率转换 格式为 00:00:00.000
        Long power = StringUtils.turnSecond(dynamometerSubsection.getPower());
        dynamometerSubsection.setPower(StringUtils.millisecondRotationTime(power));
        dynamometerSubsectionService.save(dynamometerSubsection);
        return AjaxResult.success();
    }



    /**
     * 运动员 -- 测功仪点击开始训练查询，是否已经训练 true:代表可以训练，false:代表不能训练
     */
    @Override
    public AjaxResult getDynamometerRankingOne(Integer userId , JSONObject jsonObject) {
        boolean judge = true;
        DynamometerRanking dynamometerRanking = dynamometerRankingService
                .getOne(Wrappers.<DynamometerRanking>lambdaQuery()
                        .eq(DynamometerRanking::getSportsmanId , userId)
                        .eq(DynamometerRanking::getGroupId , Integer.parseInt(jsonObject.get("groupId").toString())));
        if(StringUtils.isNotNull(dynamometerRanking)){
            judge = false;
        }
        return AjaxResult.success(judge);
    }








}
